home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 2 / Amiga Tools 2.iso / mui / mui-tools / multiuser / src / support / massign.c < prev    next >
C/C++ Source or Header  |  1995-03-09  |  11KB  |  437 lines

  1. /************************************************************
  2. * MultiUser - MultiUser Task/File Support System                *
  3. * ---------------------------------------------------------    *
  4. * Assign Clone for Non-Binding Assigns                                *
  5. * ---------------------------------------------------------    *
  6. * © Copyright 1993-1994 Geert Uytterhoeven                        *
  7. * All Rights Reserved.                                                    *
  8. ************************************************************/
  9.  
  10.  
  11. #include <exec/memory.h>
  12. #include <exec/execbase.h>
  13. #include <dos/dos.h>
  14. #include <dos/dosextens.h>
  15. #include <proto/exec.h>
  16. #include <proto/dos.h>
  17. #include <libraries/multiuser.h>
  18. #include <proto/multiuser.h>
  19. #include <string.h>
  20.  
  21. #include "MAssign_rev.h"
  22.  
  23. #include "Locale.h"
  24.  
  25. char __VersTag__[] = VERSTAG;
  26.  
  27.  
  28. #define MAXPATHLEN    512
  29.  
  30.  
  31. static BOOL AddAssign(char *name, char *target, BOOL volume, BOOL create, struct ExecBase *SysBase,
  32.                              struct DosLibrary *DOSBase, struct muBase *muBase);
  33. static struct DosPacket *WaitPktPort(struct MsgPort *port, struct ExecBase *SysBase);
  34. static ULONG GetPktOwner(struct DosPacket *pkt, struct muBase *muBase);
  35. static BPTR LockTarget(char *target, struct muUserInfo *uinfo, struct muGroupInfo *ginfo, BOOL create,
  36.                               LONG *error, struct DosLibrary *DOSBase);
  37. static void StripDevName(unsigned char *old, unsigned char *new);
  38. static void Handler(struct DosList *dlist, struct DosList *vlist, char *target, struct MsgPort *pubport,
  39.                           BOOL create, struct ExecBase *SysBase, struct DosLibrary *DOSBase,
  40.                           struct muBase *muBase);
  41.  
  42.  
  43. int __saveds Start(char *arg)
  44. {
  45.     struct ExecBase *SysBase;
  46.     struct DosLibrary *DOSBase;
  47.     struct muBase *muBase = NULL;
  48.     struct RDArgs *args;
  49.     LONG argarray[] = {
  50. #define argNAME    0
  51. #define argTARGET    1
  52. #define argVOLUME    2
  53. #define argCREATE    3
  54.         NULL, NULL, NULL, NULL
  55.     };
  56.     LONG error = NULL;
  57.     int rc = RETURN_OK;
  58.     struct muExtOwner *owner;
  59.     char *name;
  60.     int i;
  61.  
  62.     SysBase = *(struct ExecBase **)4;
  63.     
  64.     if ((!(DOSBase = (struct DosLibrary *)OpenLibrary("dos.library", 37))) ||
  65.          (!(muBase = (struct muBase *)OpenLibrary("multiuser.library", 39)))) {
  66.         rc = ERROR_INVALID_RESIDENT_LIBRARY;
  67.         goto Exit;
  68.     }
  69.     owner = muGetTaskExtOwner(NULL);
  70.     if (muGetRelationshipA(owner, NULL, NULL) & muRelF_ROOT_UID) {
  71.         args = ReadArgs("NAME/A,TARGET/A,VOLUME/S,CREATE/S", argarray, NULL);
  72.         if (!args)
  73.             error = IoErr();
  74.         else {
  75.             for (i = 0; ((char *)argarray[argNAME])[i] && (((char *)argarray[argNAME])[i] != ':'); i++);
  76.             if (((char *)argarray[argNAME])[i] != ':') {
  77.                 VPrintf(GetLocStr(MSG_INVALID_DEVICE), (char **)&argarray[argNAME]);
  78.                 rc = RETURN_ERROR;
  79.             } else if (name = AllocVec(i+1, MEMF_CLEAR|MEMF_PUBLIC)) {
  80.                 memcpy(name, (char *)argarray[argNAME], i);
  81.                 if (!AddAssign(name, (char *)argarray[argTARGET], (BOOL)argarray[argVOLUME],
  82.                                     (BOOL)argarray[argCREATE], SysBase, DOSBase, muBase))
  83.                     rc = RETURN_ERROR;
  84.                 FreeVec(name);
  85.             } else
  86.                 error = IoErr();
  87.         }
  88.         FreeArgs(args);
  89.     } else {
  90.         PutStr(GetLocStr(MSG_MUSTBEROOT));
  91.         rc = RETURN_ERROR;
  92.     }
  93.     muFreeExtOwner(owner);
  94.     if (error) {
  95.         PrintFault(error, NULL);
  96.         rc = RETURN_ERROR;
  97.     }
  98.  
  99. Exit:
  100.     CloseLibrary((struct Library *)muBase);
  101.     CloseLibrary((struct Library *)DOSBase);
  102.  
  103.     return(rc);
  104. }
  105.  
  106.  
  107.     /*
  108.      *        Add the Non-Binding Assign
  109.      */
  110.  
  111. static BOOL AddAssign(char *name, char *target, BOOL volume, BOOL create, struct ExecBase *SysBase,
  112.                              struct DosLibrary *DOSBase, struct muBase *muBase)
  113. {
  114.     struct DosList *dlist, *vlist = NULL;
  115.     struct MsgPort *port;
  116.     BOOL res = FALSE;
  117.  
  118.     if ((port = CreateMsgPort()) && (dlist = MakeDosEntry(name, DLT_DEVICE))) {
  119.         if (!volume || (vlist = MakeDosEntry(name, DLT_VOLUME))) {
  120.             dlist->dol_Task = port;
  121.             dlist->dol_misc.dol_handler.dol_SegList = -1;
  122.             dlist->dol_misc.dol_handler.dol_GlobVec = -1;
  123.             if (vlist)
  124.                 vlist->dol_Task = port;
  125.             Forbid();
  126.             if (AddDosEntry(dlist))
  127.                 if (!vlist || AddDosEntry(vlist)) {
  128.                     Permit();
  129.                     Handler(dlist, vlist, target, port, create, SysBase, DOSBase, muBase);
  130.                     res = TRUE;
  131.                 } else {
  132.                     RemDosEntry(dlist);
  133.                     Permit();
  134.                 }
  135.             else
  136.                 Permit();
  137.             if (!res)
  138.                 VPrintf(GetLocStr(MSG_ASSIGNCONFLICT), (LONG *)&name);
  139.             if (vlist)
  140.                 FreeDosEntry(vlist);
  141.         }
  142.         FreeDosEntry(dlist);
  143.     } else
  144.         PrintFault(IoErr(), NULL);
  145.  
  146.     DeleteMsgPort(port);
  147.     return(res);
  148. }
  149.  
  150.  
  151.     /*
  152.      *        Wait for a DosPacket at a specified MsgPort
  153.      */
  154.  
  155. static struct DosPacket *WaitPktPort(struct MsgPort *port, struct ExecBase *SysBase)
  156. {
  157.     struct Message *msg;
  158.     struct DosPacket *pkt = NULL;
  159.  
  160.     do
  161.         if (msg = GetMsg(port))
  162.             pkt = (struct DosPacket *)msg->mn_Node.ln_Name;
  163.         else
  164.             WaitPort(port);
  165.     while (!pkt);
  166.     return(pkt);
  167. }
  168.  
  169.  
  170.     /*
  171.      *        Get the Owner of a DosPacket
  172.      */
  173.  
  174. static ULONG GetPktOwner(struct DosPacket *pkt, struct muBase *muBase)
  175. {
  176.     struct MsgPort *port;
  177.     struct Task *task;
  178.     ULONG owner = NULL;
  179.  
  180.     if ((port = pkt->dp_Port) && (port->mp_Flags == PA_SIGNAL) && (task = port->mp_SigTask))
  181.         owner = muGetTaskOwner(task);
  182.     return(owner);
  183. }
  184.  
  185.  
  186.     /*
  187.      *        Lock the Target (and create it if necessary), resolving all Format Specifiers
  188.      */
  189.  
  190. static BPTR LockTarget(char *target, struct muUserInfo *uinfo, struct muGroupInfo *ginfo, BOOL create,
  191.                               LONG *error, struct DosLibrary *DOSBase)
  192. {
  193.     BPTR lock = NULL;
  194.     char path[MAXPATHLEN];
  195.     int len = 0, i = 0, slen;
  196.     char *str;
  197.  
  198.     *error = NULL;
  199.     while (len < MAXPATHLEN)
  200.         if (target[i])
  201.             if (target[i] == '%') {
  202.                 switch (target[i+1]) {
  203.                     case 'u':
  204.                         if (uinfo) {
  205.                             str = uinfo->UserID;
  206. Copy:                        if ((slen = strlen(str)) <= MAXPATHLEN-len) {
  207.                                 memcpy(&path[len], str, slen);
  208.                                 len += slen;
  209.                             } else {
  210.                                 *error = ERROR_LINE_TOO_LONG;
  211.                                 return(NULL);
  212.                             }
  213.                         } else {
  214. NotFound:                *error = ERROR_OBJECT_NOT_FOUND;
  215.                             return(NULL);
  216.                         }
  217.                         break;
  218.  
  219.                     case 'h':
  220.                         if (uinfo) {
  221.                             str = uinfo->HomeDir;
  222.                             goto Copy;
  223.                         } else
  224.                             goto NotFound;
  225.  
  226.                     case 'g':
  227.                         if (ginfo) {
  228.                             str = ginfo->GroupID;
  229.                             goto Copy;
  230.                         } else
  231.                             goto NotFound;
  232.  
  233.                     case '%':
  234.                         path[len++] = '%';
  235.                         break;
  236.  
  237.                     default:
  238.                         *error = ERROR_BAD_TEMPLATE;
  239.                         return(NULL);
  240.                 }
  241.                 i += 2;
  242.             } else
  243.                 path[len++] = target[i++];
  244.         else
  245.             break;
  246.     if (len < MAXPATHLEN) {
  247.         path[len] = '\0';
  248.         if (!(lock = Lock(path, ACCESS_READ)))
  249.             if (!create || !(lock = CreateDir(path)))
  250.                 *error = IoErr();
  251.             else {
  252.                 UnLock(lock);
  253.                 if (!(lock = Lock(path, ACCESS_READ)))
  254.                     *error = IoErr();
  255.             }
  256.     } else
  257.         *error = ERROR_LINE_TOO_LONG;
  258.     return(lock);
  259. }
  260.  
  261.  
  262.     /*
  263.      *        Strip the Device Name off of a File Name
  264.      *
  265.      *        Note: both old and new are CPTRs to a BSTR!
  266.      */
  267.  
  268. static void StripDevName(unsigned char *old, unsigned char *new)
  269. {
  270.     int len, i;
  271.  
  272.     len = old[0];
  273.     for (i = 0; (i < len) && (old[i+1] != ':'); i++);
  274.     if (i == len)
  275.         memcpy(new, old, len+1);
  276.     else {
  277.         memcpy(new+1, old+i+2, len-i-1);
  278.         new[0] = len-i-1;
  279.     }
  280. }
  281.  
  282.  
  283.     /*
  284.      *        Our pseudo File System
  285.      */
  286.  
  287. static void Handler(struct DosList *dlist, struct DosList *vlist, char *target, struct MsgPort *pubport,
  288.                           BOOL create, struct ExecBase *SysBase, struct DosLibrary *DOSBase,
  289.                           struct muBase *muBase)
  290. {
  291.     BOOL die = FALSE;
  292.     char *newpath = NULL;
  293.     struct Task *task;
  294.     BYTE oldpri;
  295.     struct muUserInfo *uinfo;
  296.     struct muGroupInfo *ginfo = NULL, *ginfo2;
  297.     struct MsgPort *privport, *port;
  298.     struct DosPacket *pubpkt, *privpkt;
  299.     BPTR lock;
  300.     ULONG owner;
  301.     struct TagItem tags[3];
  302.     LONG type, arg1, arg2, arg3, arg4, res1, res2;
  303.  
  304.     if ((uinfo = muAllocUserInfo()) && (ginfo = muAllocGroupInfo()) &&
  305.          (newpath = AllocVec(256, MEMF_CLEAR|MEMF_PUBLIC)) &&
  306.          (privpkt = AllocDosObject(DOS_STDPKT, NULL))) {
  307.         task = SysBase->ThisTask;
  308.         oldpri = SetTaskPri(task, 5);
  309.         privport = &((struct Process *)task)->pr_MsgPort;
  310.  
  311.         do {
  312.             pubpkt = WaitPktPort(pubport, SysBase);
  313.             type = pubpkt->dp_Type;
  314.             arg1 = pubpkt->dp_Arg1;
  315.             arg2 = pubpkt->dp_Arg2;
  316.             arg3 = pubpkt->dp_Arg3;
  317.             arg4 = pubpkt->dp_Arg4;
  318.             switch (type) {
  319.                 case ACTION_DIE:
  320.                     die = TRUE;
  321.                     ReplyPkt(pubpkt, DOSTRUE, NULL);
  322.                     break;
  323.  
  324.                 case ACTION_FINDINPUT:
  325.                 case ACTION_FINDOUTPUT:
  326.                 case ACTION_FINDUPDATE:
  327.                 case ACTION_SET_PROTECT:
  328.                 case ACTION_SET_COMMENT:
  329.                 case ACTION_SET_DATE:
  330.                 case ACTION_SET_OWNER:
  331.                 case ACTION_LOCATE_OBJECT:
  332.                 case ACTION_CREATE_DIR:
  333.                 case ACTION_DELETE_OBJECT:
  334.                 case ACTION_RENAME_OBJECT:
  335.                 case ACTION_MAKE_LINK:
  336.                 case ACTION_READ_LINK:
  337.                 case ACTION_DISK_CHANGE:
  338.                 case ACTION_IS_FILESYSTEM:
  339.                 case ACTION_CURRENT_VOLUME:
  340.                 case ACTION_FLUSH:
  341.                 case ACTION_MORE_CACHE:
  342.                     owner = GetPktOwner(pubpkt, muBase);
  343.                     uinfo->uid = (owner & muMASK_UID)>>16;
  344.                     if (muGetUserInfo(uinfo, muKeyType_uid)) {
  345.                         ginfo->gid = owner & muMASK_GID;
  346.                         ginfo2 = muGetGroupInfo(ginfo, muKeyType_gid);
  347.                         if (lock = LockTarget(target, uinfo, ginfo2, create, &res2, DOSBase)) {
  348.                             port = ((struct FileLock *)BADDR(lock))->fl_Task;
  349.                             tags[0].ti_Tag = muT_UserID;
  350.                             tags[0].ti_Data = (LONG)uinfo->UserID;
  351.                             tags[1].ti_Tag = muT_NoLog;
  352.                             tags[1].ti_Data = (LONG)TRUE;
  353.                             tags[2].ti_Tag = TAG_DONE;
  354.                             if (muLoginA(tags)) {
  355.                                 switch (type) {
  356.                                     case ACTION_FINDINPUT:
  357.                                     case ACTION_FINDOUTPUT:
  358.                                     case ACTION_FINDUPDATE:
  359.                                         ((struct FileHandle *)BADDR(arg1))->fh_Type = port;
  360.                                     case ACTION_SET_PROTECT:
  361.                                     case ACTION_SET_COMMENT:
  362.                                     case ACTION_SET_DATE:
  363.                                     case ACTION_SET_OWNER:
  364.                                         StripDevName(BADDR(arg3), newpath);
  365.                                         arg2 = lock;
  366.                                         arg3 = MKBADDR(newpath);
  367. PassPkt:                                privpkt->dp_Type = type;
  368.                                         privpkt->dp_Arg1 = arg1;
  369.                                         privpkt->dp_Arg2 = arg2;
  370.                                         privpkt->dp_Arg3 = arg3;
  371.                                         privpkt->dp_Arg4 = arg4;
  372.                                         SendPkt(privpkt, port, privport);
  373.                                         WaitPkt();
  374.                                         res1 = privpkt->dp_Res1;
  375.                                         res2 = privpkt->dp_Res2;
  376.                                         break;
  377.  
  378.                                     case ACTION_LOCATE_OBJECT:
  379.                                     case ACTION_CREATE_DIR:
  380.                                     case ACTION_DELETE_OBJECT:
  381.                                     case ACTION_RENAME_OBJECT:
  382.                                     case ACTION_MAKE_LINK:
  383.                                     case ACTION_READ_LINK:
  384.                                         StripDevName(BADDR(arg2), newpath);
  385.                                         arg1 = lock;
  386.                                         arg2 = MKBADDR(newpath);
  387.                                         goto PassPkt;
  388.  
  389.                                     case ACTION_IS_FILESYSTEM:
  390.                                     case ACTION_CURRENT_VOLUME:
  391.                                     case ACTION_FLUSH:
  392.                                     case ACTION_MORE_CACHE:
  393.                                         goto PassPkt;
  394.                                 }
  395.                                 tags[0].ti_Tag = muT_Quiet;
  396.                                 tags[0].ti_Data = TRUE;
  397.                                 tags[1].ti_Tag = TAG_DONE;
  398.                                 muLogoutA(tags);
  399.                             } else {
  400.                                 res1 = DOSFALSE;
  401.                                 res2 = ERROR_OBJECT_NOT_FOUND;
  402.                             }
  403.                             UnLock(lock);
  404.                             ReplyPkt(pubpkt, res1, res2);
  405.                         } else
  406.                             ReplyPkt(pubpkt, DOSFALSE, res2);
  407.                     } else
  408.                         ReplyPkt(pubpkt, DOSFALSE, ERROR_OBJECT_NOT_FOUND);
  409.                     break;
  410.  
  411.                 default:
  412.                     ReplyPkt(pubpkt, DOSFALSE, ERROR_ACTION_NOT_KNOWN);
  413.                     break;
  414.             }
  415.             if (die) {
  416.                 if (dlist && AttemptLockDosList(LDF_DEVICES|LDF_WRITE)) {
  417.                     if (RemDosEntry(dlist))
  418.                         dlist = NULL;
  419.                     UnLockDosList(LDF_DEVICES|LDF_WRITE);
  420.                 }
  421.                 if (vlist && AttemptLockDosList(LDF_VOLUMES|LDF_WRITE)) {
  422.                     if (RemDosEntry(vlist))
  423.                         vlist = NULL;
  424.                     UnLockDosList(LDF_VOLUMES|LDF_WRITE);
  425.                 }
  426.             }
  427.         } while (!die || dlist || vlist);
  428.         SetTaskPri(task, oldpri);
  429.         FreeDosObject(DOS_STDPKT, privpkt);
  430.     } else
  431.         PrintFault(IoErr(), NULL);
  432.  
  433.     muFreeUserInfo(uinfo);
  434.     muFreeGroupInfo(ginfo);
  435.     FreeVec(newpath);
  436. }
  437.